import XLSX from "xlsx";
import _ from "lodash";
import moment from "moment";

function saveAs(obj, fileName) {
  //当然可以自定义简单的下载文件实现方式
  let tmpa = document.createElement("a");
  tmpa.download = fileName || "下载";
  tmpa.href = URL.createObjectURL(obj); //绑定a标签
  tmpa.click(); //模拟点击实现下载
  setTimeout(function() {
    //延时释放
    URL.revokeObjectURL(obj); //用URL.revokeObjectURL()来释放这个object URL
  }, 100);
}

function s2ab(s) {
  let buf;
  if (typeof ArrayBuffer !== "undefined") {
    buf = new ArrayBuffer(s.length);
    let view = new Uint8Array(buf);
    for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
    return buf;
  }

  buf = new Array(s.length);
  for (let i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xff;
  return buf;
}

export function saveExcel(wb, fileName, type) {
  saveAs(
    new Blob(
      [s2ab(XLSX.write(wb, { bookType: type, bookSST: true, type: "binary" }))],
      {
        type: "application/octet-stream"
      }
    ),
    fileName + "." + type
  );
}

export function downloadExl(aoa, fileName, type, sheetName, merges) {
  type = type ? type : "xlsx";
  sheetName = sheetName ? sheetName : "Sheet1";
  let wb = { SheetNames: [sheetName], Sheets: {}, Props: {} };
  wb.Sheets[sheetName] = XLSX.utils.aoa_to_sheet(aoa);
  if (merges) {
    wb.Sheets[sheetName]["!merges"] = merges;
  }

  saveExcel(wb, fileName, type);
}

export const transform = obj => {
  const { el, headers, footers, fileName } = obj;
  const wb = XLSX.utils.table_to_book(el);
  const { Sheet1 } = wb.Sheets;
  const newSheet1 = {};

  const [start, end] = Sheet1["!ref"].split(":");
  const startCode = start.slice(0, 1);
  const endCode = end.slice(0, 1);
  const width = endCode.charCodeAt() - startCode.charCodeAt();
  const height = Number(end.slice(1));
  const extraHeight = (headers || []).length + (footers || []).length;

  [...headers, ...footers].forEach((item, index) => {
    const t = "s";
    const v = item;
    const key =
      index === extraHeight - 1 ? `A${height + extraHeight}` : `A${index + 1}`;
    newSheet1[key] = { t, v };
  });

  Object.keys(Sheet1).forEach(key => {
    switch (key) {
      case "!ref":
        newSheet1[key] = `${start}:${endCode + (height + extraHeight)}`;
        break;

      case "!merges":
        newSheet1[key] = generateMerges(
          Sheet1[key].slice(),
          width,
          height + extraHeight,
          headers,
          footers
        );
        break;

      default:
        const keyCode = key.slice(0, 1);
        const keyNum = Number(key.slice(1));
        newSheet1[`${keyCode + (keyNum + headers.length)}`] = Sheet1[key];
        break;
    }
  });
  wb.Sheets.Sheet1 = newSheet1;

  const wbout = XLSX.write(wb, {
    bookType: "xlsx",
    bookSST: true,
    type: "array"
  });
  const wbBlob = new Blob([wbout], { type: "application/octet-stream" });
  saveAs(wbBlob, fileName);
};

function generateMerges(arr, width, height, headers, footers) {
  const headerArrs = headers.map((item, index) => ({
    s: { r: index, c: 0 },
    e: { r: index, c: width }
  }));
  const footerArrs = footers.map((item, index) => ({
    s: { r: height - 1, c: 0 },
    e: { r: height - 1, c: width }
  }));
  const middleArrs = arr.map(obj => {
    obj.s.r += headers.length;
    obj.e.r += headers.length;
    return obj;
  });
  return [...headerArrs, ...middleArrs, ...footerArrs];
}

export function readAndParse(file, ignoreLength) {
  return new Promise(resolve => {
    const result = [];
    const reader = new FileReader();
    reader.onload = e => {
      const data = e.target.result;
      const workbook = XLSX.read(data, { type: "binary" });
      workbook.SheetNames.forEach(name => {
        const roa = XLSX.utils.sheet_to_json(workbook.Sheets[name], {
          header: 1,
          raw: false
        });
        const formatRoa = roa
          .slice(ignoreLength)
          .filter(item => item.length)
          .map(item => {
            item[0] = moment(item[0], "M/D/YY").valueOf() / 1000;
            const newItem = item.map(i => _.toNumber(i));
            return newItem;
          });
        if (formatRoa.length) result.push(...formatRoa);
      });
      resolve(result);
    };
    reader.readAsBinaryString(file);
  });
}

export function zipData(base, list) {
  const first = list.map(item => _.zipObject(base, item.slice(0, base.length)));
  // const final = formatData(first);
  return first;
}

export function formatData(list) {
  return list.map(item => {
    const result = {};
    Object.keys(item).forEach(key => {
      if (key === "_id") {
        result[key] = item[key];
        return;
      }

      const [name1, name2] = key.split("_");
      if (name2) {
        result[name2] = {
          ...(result[name2] || {}),
          [name1]: item[key]
        };
      } else {
        result[name1] = item[key];
      }
    });
    return result;
  });
}
